/**
	Copyright (c) 2009 Ozazo Pvt Ltd, INDIA

	Permission is hereby granted, free of charge, to any person or organization 
	obtaining a copy of this software and associated  documentation  files (the 
	"Software"), to deal in the Software without restriction, including without 
	limitation the rights to use, copy, modify, merge, publish, distribute, sub
	license, and/or sell copies of the Software, and to permit persons  to whom 
	the Software is furnished to do so, subject to the following conditions:
	
	The above copyright notice and  this permission notice shall be included in 
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING  BUT NOT  LIMITED  TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR  COPYRIGHT  HOLDERS  BE  LIABLE  FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY,  WHETHER  IN  AN  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
	FROM,  OUT  OF  OR  IN  CONNECTION  WITH  THE  SOFTWARE OR THE USE OR OTHER 
	DEALINGS IN THE SOFTWARE.
 */

package com.ozazo.wave.robots.fw.engines;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.google.wave.api.Blip;

import com.ozazo.wave.robots.engines.BlipDataParser;
import com.ozazo.wave.robots.engines.LateXEngine;
import com.ozazo.wave.robots.engines.WikiEngine;

/**
 * @author:  Araf Karsh Hamid
 * @version: 1.0
 * @serial:  20091121102030
 */
public class RobotContainer implements RobotContainerInterface {
	
	private final Logger log;
	private String robotName;
	
	private boolean textModified = false;
	private boolean isRealTime = false;
	
	private BlipDataParserInterface blipDataParser;	
	private List<RobotEngineInterface> engines;
	
	/**
	 * RobotContainer is built by the Robot Factory setting it with necessary parsers
	 * and Engines. 
	 */
	public RobotContainer(Logger _log) {	
		log = _log;
		robotName	= "NOBOTNAME";
	}

	/**
	 * Returns the Robot Name
	 * 
	 * @return String
	 */
	
	public String getBotName() {
		return robotName;
	}
	
	/**
	 * Sets the Robot Name
	 * 
	 * @param String _name
	 */
	
	public void setBotName(String _name) {
		if(_name != null) {
			robotName = _name;
		}
	}
	
	/**
	 * Sets whether the Robot Engine needs to be processing (the blip) in real time or not.
	 *
	 * @param boolean mode
	 */	
		
	
	public boolean isTextModified() {
		return textModified;
	}
	
	/**
	 * If real time flag is set to TRUE then the Robot will work on DOCUMENT_CHANGED event 
	 * instead of BLIP_SUBMITTED.
	 * 
	 * @param _flag
	 */
	
	public void setRealTime(boolean _flag) {
		isRealTime = _flag;
	}

	/**
	 * Sets the Blip Parsing Engine
	 * 
	 * @param _dataParser;
	 */
	
	public void setParsingEngine(BlipDataParserInterface _dataParser) {
		if(_dataParser != null) {
			blipDataParser = _dataParser;
		}
	}
	
	/**
	 * Sets a collection of engines which can process the blip.
	 * 
	 * @param List<RobotEngineInterface> _engines
	 */
	
	public void setBotEngines(List<RobotEngineInterface> _engines) {
		if(_engines != null) {
			engines = _engines;
		}
			
	}
	
	/**
	 * This method does the following steps - 
	 * --------------------------------------------------------------------------------------------------------
	 * 1. Parse the original message marked with commands (eg /w, /wd, /d etc) and create Command Object
	 * 2. Using Commands (Commands with values eg. /w Kerala or /w "The Battle of Stalingrad") from step 1
	 *    Get the result (Example: Wikipedia links mapped to values)
	 * 3. Re Create the Original Blip/Text with (WikiPedia) Links or (LateX) Images
	 * --------------------------------------------------------------------------------------------------------
	 * 
	 * @param Blip _blip
	 * @return void
	 */	
	
	public void processBlip(Blip _blip) {
		// Validate the Inputs and check if the container is ready for 
		// processing, If NOT then DO NOTHING and return the text.
		if(!validate(_blip)) {
			return;
		}
		textModified = false;		
		// The Blip / Text is passed to the BlipDataParser to parse the text
		// and create the commands object which will contain the command
		// and its value (to be processed by other Engines).		
		List<Commands> list = blipDataParser.parse(_blip.getDocument().getText(), isRealTime);		// Step 1
		if((list == null) || (list.size() == 0) ) {
			return;
		}		
		
		// Processing Multiple Engines (each engine can do the functionality of a robot
		// Each engine will work on the Command object and store the result in it.
		// A List of new set of command objects will be returned.
		// This List of Commands object is added into the Command Array List.
		
		List<List<Commands>> commands = new ArrayList<List<Commands>>();	
		for(RobotEngineInterface engine : engines) {
			commands.add(engine.processCommands(list));							// Step 2
		}		
		// If no commands found then return the Original text.
		if(commands.size() == 0) {
			return;
		}
		
		// Process the commands and results with the Blip Text message. Each Engine knows
		// how to handle the result. For example WikiEngine will create the hyper link
		// while LaTeX Engine will create the Image instead of mathematical formula 
		// instead of text.
		int x=0;
		for(RobotEngineInterface engine : engines) {
			engine.processBlip(_blip, commands.get(x));							// Step 3
			x++;
		}	
		textModified = true;
	}	

	/**
	 * Validate the Inputs. Returns true if everything is OK.
	 * 
	 * @param Blip _blip
	 * @return boolean
	 */
	
	private boolean validate(Blip _blip) {
		// Validate the Inputs and check if the container is ready for 
		// processing, If NOT then DO NOTHING and return the text.
		if((_blip ==  null)) {
			return false;														// Do Nothing if Blip is NULL
		}
		if(!checkContainerStatus()) {
			System.out.println("Container is NOT READY!");
			return false;														// Do Nothing if Container is NOT Ready
		}
		String _text = _blip.getDocument().getText();
		if( (_text == null) || (_text.trim().equals("")) ) {
			return false;														// Do Nothing if Null OR Empty Text 
		}
		if( (isRealTime) &&  (_text.length() < 5) ) {
			return false;														// Do Nothing if Text Length < 5 chars
		}
		return true;
	}
	
	/**
	 * Check the Container if its set with a Blip Data Parser and atleast one
	 * Engine to process the commands. Returns true if everything is OK.
	 * 
	 * @return boolean
	 */
	
	public boolean checkContainerStatus() {
		if(blipDataParser == null) {
			return false;
		}
		if(engines == null || engines.size() == 0) {
			return false;
		}
		return true;
	}
	
	/**
	 * --------------------------------------------------------------------------------------------------------
	 * [THIS METHOD IS MAINLY USED FOR COMMAND LINE TESTING]
	 * This method does the following steps - 
	 * --------------------------------------------------------------------------------------------------------
	 * 1. Parse the original message marked with commands (eg /w, /wd, /d etc) and create Command Object
	 * 2. Using Commands (Commands with values eg. /w Kerala or /w "The Battle of Stalingrad") from step 1
	 *    Get the result (Example: Wikipedia links mapped to values)
	 * 3. Re Create the Original Blip/Text with (WikiPedia) Links or (LateX) Images
	 * 
	 * @param String _text
	 * @return String
	 */
	
	public String processText(String _text) {
		// Validate the Inputs and check if the container is ready for 
		// processing, If NOT then DO NOTHING and return the text.
		textModified = false;
		if( (_text == null) || (_text.equals("")) ) {
			return _text;
		}
		if(!checkContainerStatus()) {
			System.out.println("Container is NOT READY!");
			return _text;														// Do Nothing if Container is NOT Ready
		}
		// The Blip / Text is passed to the BlipDataParser to parse the text
		// and create the commands object which will contain the command
		// and its value (to be processed by other Engines).
		List<Commands> list 	= blipDataParser.parse(_text, isRealTime);		// Step 1
		if((list == null) || (list.size() == 0) ) {
			return _text;
		}		
		
		// Processing Multiple Engines (each engine can do the functionality of a robot
		// Each engine will work on the Command object and store the result in it.
		// A List of new set of command objects will be returned.
		// This List of Commands object is added into the Command Array List.
		
		List<List<Commands>> commands = new ArrayList<List<Commands>>();	
		for(RobotEngineInterface engine : engines) {
			commands.add(engine.processCommands(list));							// Step 2
		}		
		// If no commands found then return the Original text.
		if(commands.size() == 0) {
			return _text;
		}
		
		// Process the commands and results with the Blip Text message. Each Engine knows
		// how to handle the result. For example WikiEngine will create the hyper link
		// while LaTeX Engine will create the Image instead of mathematical formula 
		// instead of text.
		int x=0;
		String pText = _text;
		for(RobotEngineInterface engine : engines) {
			pText = engine.processText(pText, commands.get(x));					// Step 3
			x++;
		}
		return pText;		
	}
}	// eof - RobotContainer.java ------------------------------------------------------------------